//! XML处理工具
//! 
//! 提供XML解析和生成功能

use quick_xml::events::{Event, BytesEnd, BytesStart, BytesText};
use quick_xml::{Reader, Writer};
use serde_json::Value;
use std::collections::HashMap;
use std::io::Cursor;

/// XML错误类型
#[derive(Debug, thiserror::Error)]
pub enum XmlError {
    #[error("XML parse error: {0}")]
    ParseError(String),
    #[error("XML generation error: {0}")]
    GenerationError(String),
    #[error("Quick XML error: {0}")]
    QuickXmlError(#[from] quick_xml::Error),
    #[error("JSON error: {0}")]
    JsonError(#[from] serde_json::Error),
    #[error("Attribute error: {0}")]
    AttributeError(String),
}

pub type XmlResult<T> = Result<T, XmlError>;

/// XML解析结果
#[derive(Debug, Clone)]
pub struct XmlNode {
    pub name: String,
    pub attributes: HashMap<String, String>,
    pub text: Option<String>,
    pub children: Vec<XmlNode>,
}

/// XML解析
/// 
/// 将XML字符串解析为结构化数据
/// 
/// # Examples
/// ```
/// use librarys::data::xml_utils::parse_xml;
/// 
/// let xml = r#"<root><item id="1">Hello</item></root>"#;
/// let result = parse_xml(xml).unwrap();
/// assert_eq!(result.name, "root");
/// ```
pub fn parse_xml(xml_str: &str) -> XmlResult<XmlNode> {
    let mut reader = Reader::from_str(xml_str);
    reader.trim_text(true);
    
    let mut stack: Vec<XmlNode> = Vec::new();
    let mut buf = Vec::new();
    
    loop {
        match reader.read_event_into(&mut buf)? {
            Event::Start(e) => {
                let name = String::from_utf8_lossy(e.name().as_ref()).to_string();
                
                let mut attributes = HashMap::new();
                for attr_result in e.attributes() {
                    let attr = attr_result.map_err(|e| XmlError::AttributeError(e.to_string()))?;
                    let key = String::from_utf8_lossy(attr.key.as_ref()).to_string();
                    let value = String::from_utf8_lossy(&attr.value).to_string();
                    attributes.insert(key, value);
                }
                
                let node = XmlNode {
                    name,
                    attributes,
                    text: None,
                    children: Vec::new(),
                };
                
                stack.push(node);
            }
            Event::End(_) => {
                if let Some(node) = stack.pop() {
                    if let Some(parent) = stack.last_mut() {
                        parent.children.push(node);
                    } else {
                        return Ok(node);
                    }
                }
            }
            Event::Text(e) => {
                let unescaped = e.unescape()?;
                let text = unescaped.trim();
                if !text.is_empty() {
                    if let Some(node) = stack.last_mut() {
                        node.text = Some(text.to_string());
                    }
                }
            }
            Event::Eof => break,
            _ => {}
        }
        buf.clear();
    }
    
    Err(XmlError::ParseError("Invalid XML structure".to_string()))
}

/// XML生成
/// 
/// 从JSON数据生成XML字符串
/// 
/// # Examples
/// ```
/// use librarys::data::xml_utils::generate_xml;
/// use serde_json::json;
/// 
/// let data = json!({
///     "root": {
///         "item": {
///             "@id": "1",
///             "#text": "Hello"
///         }
///     }
/// });
/// let xml = generate_xml(&data).unwrap();
/// assert!(xml.contains("<root>"));
/// ```
pub fn generate_xml(data: &Value) -> XmlResult<String> {
    let mut writer = Writer::new(Cursor::new(Vec::new()));
    
    // 写入XML声明
    writer.write_event(Event::Decl(quick_xml::events::BytesDecl::new(
        "1.0",
        Some("UTF-8"),
        None,
    )))?;
    
    // 处理根元素
    if let Value::Object(obj) = data {
        for (key, value) in obj {
            write_xml_element(&mut writer, key, value)?;
        }
    } else {
        return Err(XmlError::GenerationError("Root must be an object".to_string()));
    }
    
    let result = writer.into_inner().into_inner();
    Ok(String::from_utf8_lossy(&result).to_string())
}

fn write_xml_element(writer: &mut Writer<Cursor<Vec<u8>>>, name: &str, value: &Value) -> XmlResult<()> {
    match value {
        Value::Object(obj) => {
            let mut elem = BytesStart::new(name);
            let mut text_content = None;
            
            // 处理属性和文本内容
            for (key, val) in obj {
                if key.starts_with('@') {
                    // 属性
                    let attr_name = &key[1..];
                    if let Value::String(attr_val) = val {
                        elem.push_attribute((attr_name, attr_val.as_str()));
                    }
                } else if key == "#text" {
                    // 文本内容
                    if let Value::String(text) = val {
                        text_content = Some(text.clone());
                    }
                }
            }
            
            writer.write_event(Event::Start(elem.clone()))?;
            
            // 写入文本内容
            if let Some(text) = text_content {
                writer.write_event(Event::Text(BytesText::new(&text)))?;
            }
            
            // 处理子元素
            for (key, val) in obj {
                if !key.starts_with('@') && key != "#text" {
                    if let Value::Array(arr) = val {
                        for item in arr {
                            write_xml_element(writer, key, item)?;
                        }
                    } else {
                        write_xml_element(writer, key, val)?;
                    }
                }
            }
            
            writer.write_event(Event::End(BytesEnd::new(name)))?;
        }
        Value::String(s) => {
            writer.write_event(Event::Start(BytesStart::new(name)))?;
            writer.write_event(Event::Text(BytesText::new(s)))?;
            writer.write_event(Event::End(BytesEnd::new(name)))?;
        }
        Value::Number(n) => {
            writer.write_event(Event::Start(BytesStart::new(name)))?;
            writer.write_event(Event::Text(BytesText::new(&n.to_string())))?;
            writer.write_event(Event::End(BytesEnd::new(name)))?;
        }
        Value::Bool(b) => {
            writer.write_event(Event::Start(BytesStart::new(name)))?;
            writer.write_event(Event::Text(BytesText::new(&b.to_string())))?;
            writer.write_event(Event::End(BytesEnd::new(name)))?;
        }
        Value::Array(arr) => {
            for item in arr {
                write_xml_element(writer, name, item)?;
            }
        }
        Value::Null => {
            writer.write_event(Event::Empty(BytesStart::new(name)))?;
        }
    }
    
    Ok(())
}

/// XML转换为JSON
/// 
/// 将XML节点转换为JSON值
/// 
/// # Examples
/// ```
/// use librarys::data::xml_utils::{parse_xml, xml_to_json};
/// 
/// let xml = r#"<root><item>Hello</item></root>"#;
/// let node = parse_xml(xml).unwrap();
/// let json = xml_to_json(&node);
/// assert!(json.is_object());
/// ```
pub fn xml_to_json(node: &XmlNode) -> Value {
    let mut obj = serde_json::Map::new();
    
    // 添加属性
    for (key, value) in &node.attributes {
        obj.insert(format!("@{}", key), Value::String(value.clone()));
    }
    
    // 添加文本内容
    if let Some(text) = &node.text {
        if node.children.is_empty() {
            return Value::String(text.clone());
        } else {
            obj.insert("#text".to_string(), Value::String(text.clone()));
        }
    }
    
    // 添加子元素
    let mut children_map: HashMap<String, Vec<Value>> = HashMap::new();
    for child in &node.children {
        children_map.entry(child.name.clone())
            .or_insert_with(Vec::new)
            .push(xml_to_json(child));
    }
    
    for (name, values) in children_map {
        if values.len() == 1 {
            obj.insert(name, values.into_iter().next().unwrap());
        } else {
            obj.insert(name, Value::Array(values));
        }
    }
    
    Value::Object(obj)
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json::json;

    #[test]
    fn test_xml_parsing() {
        let xml = r#"<root><item id="1">Hello</item><item id="2">World</item></root>"#;
        let result = parse_xml(xml).unwrap();
        
        assert_eq!(result.name, "root");
        assert_eq!(result.children.len(), 2);
        assert_eq!(result.children[0].name, "item");
        assert_eq!(result.children[0].attributes.get("id"), Some(&"1".to_string()));
        assert_eq!(result.children[0].text, Some("Hello".to_string()));
    }

    #[test]
    fn test_xml_generation() {
        let data = json!({
            "root": {
                "item": {
                    "@id": "1",
                    "#text": "Hello"
                }
            }
        });
        
        let xml = generate_xml(&data).unwrap();
        assert!(xml.contains("<root>"));
        assert!(xml.contains("<item id=\"1\">Hello</item>"));
        assert!(xml.contains("</root>"));
    }

    #[test]
    fn test_xml_to_json() {
        let xml = r#"<root><item id="1">Hello</item></root>"#;
        let node = parse_xml(xml).unwrap();
        let json = xml_to_json(&node);
        
        assert!(json.is_object());
        let root_obj = json.as_object().unwrap();
        assert!(root_obj.contains_key("item"));
    }

    #[test]
    fn test_simple_xml() {
        let xml = r#"<message>Hello World</message>"#;
        let result = parse_xml(xml).unwrap();
        
        assert_eq!(result.name, "message");
        assert_eq!(result.text, Some("Hello World".to_string()));
        assert!(result.children.is_empty());
    }
}